<?php

/* 
 * Copyright (c) 2009, Nguyen Duc Thuan <me@ndthuan.com>
 * All rights reserved.
 */

class Fete_View_Helper_Form extends Fete_View_Helper
{
    protected $_binder      = null;
    protected $_isXhtml     = false;
    protected $_isPost    = false;
    protected $_autoId      = true;
    protected $_selectedProperty = null;
    protected $_checkedProperty = null;
    protected $_multipleProperty = 'true';

    /**
     *
     * @return Fete_View_Helper_Form
     */
    public function &form()
    {
        return $this;
    }

    /**
     * @deprecated
     */
    public function hidden($name, $value = '')
    {
        $extras['type']     = 'hidden';
        $extras['name']     = $name;
        if ($this->_autoId) {
            $extras['id'] = $name;
        }
        $extras['value']    = $value;

        return $this->_write('input', '', $extras, false);
    }

    public function text($name, $value = '')
    {
        return htmlspecialchars(isset($this->_binder[$name])
            ? $this->_binder[$name] : $value);
    }

    public function textMultiple($name, $values, $extras = array())
    {

    }

    public function password($name, $value = '')
    {
        return htmlspecialchars(isset($this->_binder[$name])
            ? $this->_binder[$name] : $value);
    }

    public function textarea($name, $value)
    {
        return
            htmlspecialchars(isset($this->_binder[$name]) ?
            $this->_binder[$name] : $value);
    }

    public function radio($name, $value, $isDefault = false)
    {
        $checkedHtml = '';
        if ((isset($this->_binder[$name]) && $value == $this->_binder[$name]) ||
            (!isset($this->_binder[$name]) && $isDefault)) {
            $checkedHtml = 'checked="' . $this->_checkedProperty . '"';
        }

        return $checkedHtml;
    }

    public function checkbox($name, $value, $checked = false)
    {
        $checkedHtml = '';

        if ((isset($this->_binder[$name]) && $value == $this->_binder[$name]) ||
            (!$this->_isPost && $checked)) {
            $checkedHtml = 'checked="' . $this->_checkedProperty . '"';
        }

        return $checkedHtml;
    }

    public function checkboxGroupList($name, $values, $defaults = array()
        , $separator = '')
    {
        $maxValueIndex = count($values) - 1;
        ob_start();
        foreach ($values as $offset => $value)
        {
            $properties = array(
                'type' => 'checkbox',
                'name' => $name . '[]',
                'id' => $name . '_' . $offset,
                'value' => $value
            );

            if (    (isset($this->_binder[$name])
                && in_array($value, $this->_binder[$name]))
                ||  (!$this->_isPost && in_array($value, $defaults))) {
                $properties['checked'] = $this->_checkedProperty;
            }

            echo '<label for="', $name, '_', $offset, '">'
            , $this->_write('input', '', $properties, false)
            , ' ', $value, '</label>';

            if ($offset < $maxValueIndex) {
                echo $separator;
            }
        }

        return ob_get_clean();
    }

    public function checkboxGroupAssoc($name, $values
        , $defaults = array(), $separator = '')
    {
        $maxValueIndex = count($values) - 1;
        $counter = -1;
        ob_start();
        foreach ($values as $value => $label)
        {
            ++$counter;
            $properties = array(
                'type' => 'checkbox',
                'name' => $name . '[]',
                'id' => $name . '_' . $counter,
                'value' => $value
            );

            if (
            (isset($this->_binder[$name])
                && in_array($value, $this->_binder[$name]))
                || (!$this->_isPost && in_array($value, $defaults))) {
                $properties['checked'] = $this->_checkedProperty;
            }

            echo '<label for="', $name, '_', $counter, '">',
            $this->_write('input', '', $properties, false), ' ', $label
            , '</label>';

            if ($counter < $maxValueIndex) {
                echo $separator;
            }
        }

        return ob_get_clean();
    }

    public function checkboxGroupGrid($name, $values
        , $defaults = array(), $separator = '')
    {
        if (isset($values[0])) {
            $fields = array_keys($values[0]);
            $valueKey = $fields[0];
            $labelKey = $fields[1];
        }

        $maxIndex = count($values) - 1;

        ob_start();
        foreach ($values as $offset => $row)
        {
            $properties = array(
                'type' => 'checkbox',
                'name' => $name . '[]',
                'id' => $name . '_' . $offset,
                'value' => $row[$valueKey]
            );

            if (
            (isset($this->_binder[$name])
                && in_array($row[$valueKey], $this->_binder[$name]))
                || (!$this->_isPost
                && in_array($row[$valueKey], $defaults))) {
                $properties['checked'] = $this->_checkedProperty;
            }

            echo '<label for="', $name, '_', $offset, '">'
            , $this->_write('input', '', $properties, false), ' '
            , $row[$labelKey], '</label>';

            if ($offset < $maxIndex) {
                echo $separator;
            }
        }

        return ob_get_clean();
    }

    public function selectList($name, $values, $default = null)
    {
        ob_start();
        foreach ($values as $value)
        {
            $optionAttribs = array('value' => $value);

            if (
            (isset($this->_binder[$name])
                && $value == $this->_binder[$name])
                || (!isset($this->_binder[$name])
                && $value == $default)) {
                $optionAttribs['selected'] = $this->_selectedProperty;
            }

            echo $this->_write('option', $value, $optionAttribs, true);
        }

        return ob_get_clean();
    }

    public function selectMultipleList($name, $values, $defaults = array())
    {
        ob_start();
        foreach ($values as $value)
        {
            $optionAttribs = array('value' => $value);

            if (
            (isset($this->_binder[$name])
                && in_array($value, $this->_binder[$name]))
                || (!isset($this->_binder[$name])
                && in_array($value, $defaults))) {
                $optionAttribs['selected'] = $this->_selectedProperty;
            }

            echo $this->_write('option', $value, $optionAttribs, true);
        }

        return ob_get_clean();
    }

    public function selectAssoc($name, $values, $default = null)
    {
        ob_start();
        foreach ($values as $value => $label)
        {
            $optionAttribs = array('value' => $value);

            if (
            (isset($this->_binder[$name])
                && $value == $this->_binder[$name])
                || (!isset($this->_binder[$name])
                && $value == $default)) {

                $optionAttribs['selected'] = $this->_selectedProperty;
            }

            echo $this->_write('option', $label, $optionAttribs, true);
        }

        return ob_get_clean();
    }

    public function selectMultipleAssoc($name, $values, $defaults = array())
    {
        ob_start();
        foreach ($values as $value => $label)
        {
            $optionAttribs = array('value' => $value);

            if (
            (isset($this->_binder[$name])
                && in_array($value, $this->_binder[$name]))
                || (!isset($this->_binder[$name])
                && in_array($value, $defaults))) {
                $optionAttribs['selected'] = $this->_selectedProperty;
            }

            echo $this->_write('option', $label, $optionAttribs, true);
        }

        return ob_get_clean();
    }

    public function selectGrid($name, $dataList, $defaultValue = null)
    {
        if (isset($dataList[0])) {
            $fields = array_keys($dataList[0]);
            $valueKey = $fields[0];
            $labelKey = $fields[1];
        }

        ob_start();
        foreach ($dataList as $dataItem)
        {
            $optionAttribs = array('value' => $dataItem[$valueKey]);

            if (
            (isset($this->_binder[$name])
                && $dataItem[$valueKey] == $this->_binder[$name])
                || (!isset($this->_binder[$name])
                && $dataItem[$valueKey] == $defaultValue)) {
                $optionAttribs['selected'] = $this->_selectedProperty;
            }

            echo $this->_write('option', $dataItem[$labelKey]
            , $optionAttribs, true);
        }

        return ob_get_clean();
    }

    public function selectMultipleGrid($name, $values, $defaults)
    {
        if (isset($values[0])) {
            $fields = array_keys($values[0]);
            $valueKey = $fields[0];
            $labelKey = $fields[1];
        }

        ob_start();
        foreach ($values as $row)
        {
            $optionAttribs = array('value' => $row[$valueKey]);

            if (
            (isset($this->_binder[$name])
                && in_array($row[$valueKey], $this->_binder[$name]))
                || (!isset($this->_binder[$name])
                && in_array($row[$valueKey], $defaults))) {
                $optionAttribs['selected'] = $this->_selectedProperty;
            }

            echo $this->_write('option', $row[$labelKey], $optionAttribs, true);
        }

        return ob_get_clean();
    }

    /**
     * @deprecated
     */
    public function file($name, $extras = array())
    {
        $extras['type'] = 'file';
        $extras['name'] = $name;
        if ($this->_autoId) {
            $extras['id'] = $name;
        }

        return $this->_write('input', '', $extras, false);
    }

    /**
     * @deprecated
     */
    public function button($type, $value, $name = null, $extras = array())
    {
        $extras['type'] = $type;
        if (null !== $name) {
            $extras['name'] = $name;
            if ($this->_autoId) {
                $extras['id'] = $name;
            }
        }
        $extras['value'] = $value;

        return $this->_write('input', '', $extras, false);
    }

    protected function _write($tag, $innerText = '', $attribs = array()
        , $closeTag = true)
    {
        if (!$this->_isXhtml) {
            $tag = strtoupper($tag);
        }

        ob_start();
        echo '<', $tag;

        foreach ($attribs as $attrib => $value)
        {
            echo ' ', $attrib, (null !== $value
            ? '="' . (is_string($value)
                ? htmlspecialchars($value) : $value) . '"'
            : '');
        }

        if ($closeTag) {
            echo '>', $innerText, '</', $tag, '>';
        } else {
            if ($this->_isXhtml) {
                echo ' />';
            } else {
                echo '>';
            }
        }

        return ob_get_clean();
    }

    /**
     *
     * @param array $binder
     * @return Fete_View_Helper_Form
     */
    public function &setBinder($binder)
    {
        $this->_binder = $binder;

        return $this;
    }

    /**
     *
     * @param bool $auto
     * @return Fete_View_Helper_Form
     */
    public function &setAutoId($auto)
    {
        $this->_autoId = $auto;

        return $this;
    }

    public function __construct($data = null)
    {
        $this->_isPost  = 'POST' === $_SERVER['REQUEST_METHOD'];

        if (null === $data) {
            $data = $this->_isPost ? $_POST : $_GET;
        }
        
        $this->_binder  = $data;

        $this->_isXhtml =
            'XHTML' === substr($this->docType()->getDocType(), 0, 5);

        if ($this->_isXhtml) {
            $this->_selectedProperty = 'selected';
            $this->_checkedProperty = 'checked';
            $this->_multipleProperty = 'multiple';
        }
    }
}